package com.webank.wedatasphere.qualitis.question.service.impl;

import com.webank.wedatasphere.qualitis.controller.request.PageReqDto;
import com.webank.wedatasphere.qualitis.dao.UserDao;
import com.webank.wedatasphere.qualitis.entity.User;
import com.webank.wedatasphere.qualitis.question.constant.OrderStatus;
import com.webank.wedatasphere.qualitis.question.entity.Order;
import com.webank.wedatasphere.qualitis.question.repository.OrderRepository;
import com.webank.wedatasphere.qualitis.question.service.OrderService;
import com.webank.wedatasphere.qualitis.question.service.dto.UserDto;
import com.webank.wedatasphere.qualitis.question.service.transform.OrderTransform;
import com.webank.wedatasphere.qualitis.response.Grid;
import com.webank.wedatasphere.qualitis.util.CommUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderRepository orderRepository;

    @Resource
    private UserDao userDao;

    @Override
    public Grid<Order> dataGrid(Order order, PageReqDto dto) {
        int current = dto.getPage();
        int pageSize = dto.getRows();
        String filters = dto.getFilterRules();

        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
//        // 获取条件过滤器
//        JSONObject changeBuilder = CommUtils.getJsonObject(filters);
//        // 组装SQl条件过滤法器
//        ExampleMatcher matcher = CommUtils.getSqlWhere(filters);
//
//        // 序列化对象
//        Order itemQueryWhere = changeBuilder.toJavaObject(Order.class);

        // 分页插件
        Pageable pageable = PageRequest.of(current - 1, pageSize, sort);
//        // 条件过滤器插件
//        Example<Order> example = Example.of(itemQueryWhere, matcher);
//        // 条件过滤+分页
//        Page<Order> all = orderRepository.findAll(example, pageable);
        Page<Order> all = orderRepository.findAll(CommUtils.tableFilterSpec(filters, order), pageable);

        List<Order> content = all.getContent();
        long totalElements = all.getTotalElements();
        return Grid.OkPage(content, totalElements);
    }

    @Override
    public Order get(Long id) {
        return orderRepository.findById(id).orElseGet(Order::new);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Order save(Order order) {
        if(order.getTaskId() == null){
            return new Order();
        }
        if(order.getId() == null) {
            order.setCreateTime(new Date());
            order.setStatus(OrderStatus.NOT_RESOLVE.getCode());
        }
        return orderRepository.save(order);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int close(List<Long> ids) {
        List<Order> orderList = orderRepository.findAllById(ids);
        for (Order order : orderList) {
            if (OrderStatus.getByCode(order.getStatus()) != OrderStatus.RESOLVED) {
                return 0;
            }
            order.setStatus(OrderStatus.CLOSED.getCode());
            order.setUpdateTime(new Date());
        }
        List<Order> savedAll = orderRepository.saveAll(orderList);
        return savedAll.size();
    }

    @Override
    public List<UserDto> getOrderUsers() {
        return orderRepository.findAll(groupByHandler()).stream().map(OrderTransform::orderToUserDto).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int assign(List<Long> ids, Long handler) {
        List<Order> orderList = orderRepository.findAllById(ids);
        User user = userDao.findById(handler);
        for (Order order : orderList) {
            if (OrderStatus.getByCode(order.getStatus()) != OrderStatus.NOT_RESOLVE) {
                return 0;
            }
            order.setHandler(handler);
            order.setHandlerName(user.getChineseName());
            order.setUpdateTime(new Date());
        }
        List<Order> savedAll = orderRepository.saveAll(orderList);
        return savedAll.size();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int doReturn(List<Long> ids) {
        List<Order> orderList = orderRepository.findAllById(ids);
        Date now = new Date();
        for (Order order : orderList) {
            if (OrderStatus.getByCode(order.getStatus()) != OrderStatus.RESOLVED) {
                return 0;
            }
            order.setUpdateTime(now);
            order.setStatus(OrderStatus.RETURN.getCode());
            order.setReturnTime(now);
        }
        List<Order> savedAll = orderRepository.saveAll(orderList);
        return savedAll.size();
    }

    public static Specification<Order> groupByHandler() {
        return (root, query, builder) -> {
            query.groupBy(root.get("handler"), root.get("handlerName"));
            return query.getRestriction();
        };
    }

}
